﻿/*
Copyright (c) 2011 <a href="http://www.gutgames.com">James Craig</a>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/ 

#region Usings
using System.Collections.Generic;
using HaterAide.Cache.Interfaces;
using HaterAide.SQL.Interfaces;
using HaterAide.SQL.Interfaces.SQL;
#endregion

namespace HaterAide
{
    /// <summary>
    /// Session class
    /// </summary>
    public class Session
    {
        #region Constructor

        /// <summary>
        /// Constructor
        /// </summary>
        public Session()
        {
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="Provider">SQL Providers</param>
        /// <param name="Cache">Cache Provider</param>
        internal Session(List<IProvider> Providers, ICache Cache)
        {
            this.Providers = Providers;
            this.Cache = Cache;
            foreach (IProvider Provider in Providers)
            {
                Provider.Cache = Cache;
            }
        }

        #endregion

        #region Public Functions

        /// <summary>
        /// Saves an object
        /// </summary>
        /// <param name="Object">Object to save</param>
        /// <returns>true if it is saved, false otherwise</returns>
        public bool Save(object Object)
        {
            bool ReturnValue = false;
            if (Providers != null)
            {
                foreach (IProvider Provider in Providers)
                {
                    ReturnValue = Provider.Save(Object, this);
                }
            }
            return ReturnValue;
        }

        /// <summary>
        /// Selects an object from the database by ID
        /// </summary>
        /// <typeparam name="T">Type of the output object</typeparam>
        /// <param name="ID">ID of the object</param>
        /// <param name="Object">Object that is returned to the user</param>
        public void Select<T>(object ID, out T Object)
        {
            Object = default(T);
            if (Providers != null)
            {
                foreach (IProvider Provider in Providers)
                {
                    Object = (T)Provider.SelectByID<T>(ID, this, Object);
                }
            }
        }

        /// <summary>
        /// Selects all of a specific type of object
        /// </summary>
        /// <typeparam name="T">The object type</typeparam>
        /// <param name="Object">The list of objects</param>
        public void SelectAll<T>(out List<T> Object)
        {
            if (Providers[0] != null)
            {
                Object = (List<T>)Providers[0].SelectAll<T>(this);
                return;
            }
            Object = new List<T>();
        }

        /// <summary>
        /// Selects a set of objects based off of a where statement
        /// </summary>
        /// <typeparam name="T">The type of the objects</typeparam>
        /// <param name="Object">The list of objects</param>
        /// <param name="Clause">The where clause</param>
        /// <param name="OrderBy">The order by clause</param>
        /// <param name="Start">Start of the list to return (used for paging)</param>
        /// <param name="End">End of the list to return (used for paging)</param>
        public void SelectWhere<T>(out List<T> Object, IClause<T> Clause, IClause<T> OrderBy, int Start = 1, int End = -1)
        {
            if (Providers[0] != null)
            {
                Object = (List<T>)Providers[0].SelectWhere<T>(Clause, OrderBy, this, Start, End);
                return;
            }
            Object = new List<T>();
        }

        /// <summary>
        /// Selects a list of items based on a user defined stored procedure
        /// </summary>
        /// <typeparam name="T">The type of the objects returned</typeparam>
        /// <param name="Object">The object list</param>
        /// <param name="StoredProcedureName">The name of the stored procedure</param>
        /// <param name="Variables">A list of variables to be used in the stored procedure</param>
        public void SelectStoredProcedure<T>(out List<T> Object, string StoredProcedureName, List<IVariable> Variables)
        {
            if (Providers[0] != null)
            {
                Object = (List<T>)Providers[0].SelectStoredProcedure<T>(StoredProcedureName, Variables, this);
                return;
            }
            Object = new List<T>();
        }

        /// <summary>
        /// Selects a list of items based on a user defined SQL text
        /// </summary>
        /// <typeparam name="T">The type of the objects returned</typeparam>
        /// <param name="Object">The object list</param>
        /// <param name="SQLText">The SQL text</param>
        /// <param name="Variables">A list of variables to be used in the stored procedure</param>
        public void SelectSQLText<T>(out List<T> Object, string SQLText, List<IVariable> Variables)
        {
            if (Providers[0] != null)
            {
                Object = (List<T>)Providers[0].SelectSQLText<T>(SQLText, Variables, this);
                return;
            }
            Object = new List<T>();
        }

        /// <summary>
        /// Selects a list of objects associated with another object (used internally)
        /// </summary>
        /// <typeparam name="P">Input type</typeparam>
        /// <typeparam name="T">Output type</typeparam>
        /// <param name="ID">The input type's ID</param>
        /// <param name="Object">The list of objects that are returned</param>
        /// <param name="FieldName">The name of the table that is used</param>
        public void SelectList<P, T>(object ID, out List<T> Object, string FieldName)
        {
            if (Providers[0] != null)
            {
                Object = (List<T>)Providers[0].SelectListByID<P, T>(ID, FieldName, this);
                return;
            }
            Object = default(List<T>);
        }

        /// <summary>
        /// Deletes an object from the database
        /// </summary>
        /// <param name="Object">Object to delete</param>
        public void Delete(object Object)
        {
            if (Providers != null)
            {
                foreach (IProvider Provider in Providers)
                {
                    Provider.Delete(Object, this);
                }
            }
        }

        #endregion

        #region Private Variables

        private List<IProvider> Providers { get; set; }
        private ICache Cache { get; set; }

        #endregion
    }
}